abstract class Component {
  protected componentName: string

  constructor(componentName: string) {
    this.componentName = componentName
  }

  // 增加 分支/叶子 节点方法
  abstract Add(component: Component): void
  // 移除 分支/叶子 节点方法
  abstract Remove(component: Component): void
  // 按照深度显示树形结构的方法
  abstract Show(depth: number): void
}

class Composite extends Component {
  private childrenList: Array<Component> = new Array<Component>()

  constructor(componentName) {
    super(componentName)
  }

  Add(component: Component) {
    this.childrenList.push(component)
  }

  Remove(component: Component): void {
    this.childrenList.filter(item => item === component)
  }

  Show(depth: number): void {
    for (let i = 0; i < depth; i++) {
      console.log('+')
    }

    console.log(this.componentName + '\n')

    for (let i = 0; i < this.childrenList.length; i++) {
      this.childrenList[i].Show(depth + 2)
    }
  }
}

class Leaf extends Component {
  constructor(componentName: string) {
    super(componentName)
  }

  Add(component: Component): void {
    console.log("叶子节点无法添加节点")
  }

  Remove(component: Component): void {
    console.log("叶子节点无法删除节点")
  }

  Show(depth: number): void {
    for (let i = 0; i < depth; i++) {
      console.log('+')
    }

    console.log(this.componentName + '\n')
  }
}

(function () {

  // 创建一棵树
  let root = new Composite("树根")
  root.Add(new Leaf("叶子A"))
  root.Add(new Leaf("叶子B"))

  // 节点1 及其叶子
  let composite1 = new Composite("结点X")
  composite1.Add(new Leaf('叶子节点 XA'))
  composite1.Add(new Leaf('叶子节点 XB'))

  // 节点2 及其叶子
  let composite2 = new Composite("结点Y")
  composite2.Add(new Leaf('叶子节点 YA'))
  composite2.Add(new Leaf('叶子节点 YB'))

  // 拼接节点
  composite1.Add(composite2)
  root.Add(composite1)

  // 展示整颗树
  root.Show(1)
}())